#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <errno.h>
#include <time.h>         // 新增：用于获取时间戳
#include <sys/stat.h>     // 新增：用于获取文件状态信息

#define MAX_CLIENTS 3     // 最大客户端连接数
#define BUFFER_SIZE 1024  // 缓冲区大小
#define MAX_FILE_SIZE (1 * 1024 * 1024) // 日志文件最大1MB
#define LOG_FILENAME "sensor.log" // 日志文件名

// 从字符串中解析传感器数据
void extractData(const char* input, float *temperature, float *light);
// 从config.ini读取配置参数
int getparameter(char *key, char *value);

int main() {
    // 从配置文件读取IP和端口
    char port[100] = {0};
    char ip[100] = {0};
    if (getparameter("port", port) != 0) {
        strcpy(port, "9004"); // 默认端口
        printf("警告：使用默认端口 9004\n");
    }
    if (getparameter("ip", ip) != 0) {
        strcpy(ip, "0.0.0.0"); // 默认监听所有IP
        printf("警告：使用默认IP 0.0.0.0\n");
    }

    // 初始化服务器socket
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port));
    addr.sin_addr.s_addr = inet_addr(ip);
    
    // 设置socket选项（允许端口复用）
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
    
    // 绑定并监听
    if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("绑定失败");
        exit(EXIT_FAILURE);
    }
    listen(server_fd, 5);

    fd_set readfds;
    int max_fd, activity;
    int client_sockets[MAX_CLIENTS] = {0}; // 客户端socket数组
    float temperature, light; // 传感器数据

    printf("服务器启动，监听 %s:%s\n", ip, port);

    // 主循环
    while(1) {
        FD_ZERO(&readfds);
        FD_SET(server_fd, &readfds);
        max_fd = server_fd;

        // 将客户端socket加入监控集合
        for (int i = 0; i < MAX_CLIENTS; i++) {
            int sd = client_sockets[i];
            if (sd > 0) {
                FD_SET(sd, &readfds);
                if (sd > max_fd) max_fd = sd;
            }
        }

        // 使用select监控socket活动
        activity = select(max_fd + 1, &readfds, NULL, NULL, NULL);
        if ((activity < 0) && (errno != EINTR)) {
            perror("select错误");
        }

        // 处理新连接
        if (FD_ISSET(server_fd, &readfds)) {
            struct sockaddr_in client_addr;
            socklen_t addrlen = sizeof(client_addr);
            int new_socket = accept(server_fd, (struct sockaddr*)&client_addr, &addrlen);
            if (new_socket < 0) {
                perror("接受连接失败");
                continue;
            }

            // 将新socket加入空闲位置
            for (int i = 0; i < MAX_CLIENTS; i++) {
                if (client_sockets[i] == 0) {
                    client_sockets[i] = new_socket;
                    printf("新客户端连接，socket fd: %d\n", new_socket);
                    break;
                }
            }
        }

        // 处理客户端数据
        for (int i = 0; i < MAX_CLIENTS; i++) {
            int sd = client_sockets[i];
            if (sd > 0 && FD_ISSET(sd, &readfds)) {
                char buffer[BUFFER_SIZE] = {0};
                int bytes_recv = recv(sd, buffer, BUFFER_SIZE, 0);

                // 提取传感器数据
                extractData(buffer, &temperature, &light);

                if (bytes_recv <= 0) { // 连接关闭或错误
                    printf("客户端断开，socket fd: %d\n", sd);
                    close(sd);
                    client_sockets[i] = 0;
                } else {
                    // 判断请求类型
                    if (strstr(buffer, "HTTP/1.1") || strstr(buffer, "GET") || strstr(buffer, "POST")) {
                        // 处理HTTP请求（手机APP）
                        printf("收到HTTP请求:\n%s\n", buffer);
                        
                        // 生成JSON响应
                        char response[128];
                        // snprintf(response, sizeof(response),
                        //         "HTTP/1.1 200 OK\r\n\r\n[\"当前温度：%.1f 'C\",\"当前亮度：%.0f %%\",\"待添加\"]",
                        //         temperature, 
                        //         light);
                        snprintf(response, sizeof(response),
                                "HTTP/1.1 200 OK\r\n\r\n[\"当前温度：%.1f 'C\",\"当前亮度：%.0f %%\",\"待添加\"]",
                                temperature, 
                                light);
                        send(sd, response, strlen(response), 0);
                        close(sd); // HTTP短连接，关闭socket
                        client_sockets[i] = 0;
                    } else {
                        // 处理STM32数据
                        printf("STM32 Data: %s\n", buffer);
                        send(sd, "ACK", 3, 0); // 发送确认

                        /* 新增：记录数据到日志文件 */
                        // 获取当前时间
                        time_t now = time(NULL);
                        struct tm *tm_info = localtime(&now);
                        char time_str[20];
                        strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);

                        // 写入日志文件
                        FILE *fp = fopen(LOG_FILENAME, "a");
                        if (fp == NULL) {
                            perror("无法打开日志文件");
                        } else {
                            fprintf(fp, "[%s] %s\n", time_str, buffer);
                            fclose(fp);

                            // 检查文件大小
                            struct stat st;
                            if (stat(LOG_FILENAME, &st) == 0) {
                                if (st.st_size > MAX_FILE_SIZE) {
                                    // 生成带时间戳的新文件名
                                    char new_name[64];
                                    strftime(new_name, sizeof(new_name), "sensor_%Y%m%d%H%M%S.log", tm_info);
                                    rename(LOG_FILENAME, new_name); // 文件轮转
                                    printf("日志文件已轮转为: %s\n", new_name);
                                }
                            } else {
                                perror("无法获取文件状态");
                            }
                        }
                    }
                }
            }
        }
    }
    close(server_fd);
    return 0;
}

// 从数据字符串提取温度和亮度
void extractData(const char* input, float *temperature, float *light) {
    // 使用 sscanf 从输入字符串中提取温度和百分比
    sscanf(input, "Temp: %f'C, Light: %*[^()](%f%%)", temperature, light);
}
// void extractData(const char* input, float *temperature, float *light) {
//     // 格式说明：
//     // %f'C  : 读取温度值（如 26.8）
//     // %*fV  : 跳过电压值（如 1.93V）
//     // (%f%%) : 读取括号内的百分比（如 58.6%）
//     int parsed = sscanf(input, "Temp: %f'C, Light: %*fV (%f%%)", temperature, light);
    
//     if (parsed != 2) {
//         printf("解析失败！原始数据: %s\n", input);
//         *temperature = 0.0f;
//         *light = 0.0f;
//     } else {
//         printf("调试：温度=%.1f'C，亮度=%.1f%%\n", *temperature, *light);
//     }
// }

// 从config.ini读取键值
int getparameter(char *key, char *value) {
    FILE *file = fopen("config.ini", "r");
    if (!file) return -1;

    char line[100];
    while (fgets(line, sizeof(line), file)) {
        line[strcspn(line, "\n")] = '\0'; // 去换行符

        char *current_key = strtok(line, "=");
        if (current_key && strcmp(key, current_key) == 0) {
            char *current_value = strtok(NULL, "=");
            if (current_value) {
                strcpy(value, current_value);
                fclose(file);
                return 0;
            }
        }
    }
    fclose(file);
    return -1;
}